One way would be to keep track of which years you’ve already printed. Using your code:
<?php
$args = array(
'post_type' => 'attachment',
'post_mime_type' => 'image',
'numberposts' => -1,
'orderby' => 'menu_order',
'order' => ASC
);
$attachments = get_posts( $args );
echo '<table id="bibliography">';
if ( $attachments ) {
$already_printed_years = array();
foreach ( $attachments as $post ) {
setup_postdata( $post );
echo '<tr><td>';
$year = get_post_meta( $post->ID, '_publication_year', true );
if ( get_post_meta( $post->ID, '_publication_year', true ) && ! in_array( $year, $already_printed_years ) ) {
echo get_post_meta( $post->ID, '_publication_year', true );
$already_printed_years[] = $year;
}
echo '</td><td>';
echo '<a href="' . get_permalink( $post->ID ) . '">';
echo get_the_excerpt();
echo '</a></td></tr>';
}
}
echo '</table>';