Custom product loop avoiding duplicates

Using the developers’ reference example, you are referencing $loop redundantly. Drop the $loop-> before the_post() and have_posts():

if ( have_posts() ) {
    $term_names = array();
    while ( have_posts() ) {

        the_post(); 
        $myPostID = get_the_ID();

        //Uncomment next 3 lines to debug using your error log
        //ob_start();
        //var_dump($myPostID);
        //error_log('myPostID = ' . ob_get_clean(),0);

        $arrProductTerms = wc_get_product_terms( $myPostID, 'pa_product-series' );

        //Uncomment next 3 lines to debug using your error log
        //ob_start();
        //var_dump($arrProductTerms);
        //error_log('arrProductTerms=" . ob_get_clean(),0);

        foreach($arrProductTerms as $att){
           // prevent later values from overwriting existing...
           // Also, I believe $att is an object with properties, so you need to choose which one should be unique. I chose "slug"
           if (!array_key_exists($att->slug,$term_names)) $term_names[$att->slug]=$att;
        } // loop foreach

    } // loop while
    // sort by key ($att->slug)
    ksort($term_names);

    // Used array_keys because we stored $att as objects
    echo "<span>' . implode( '</span>, <span>', array_keys($term_names) ) . '</span> ';

} else {
    echo '<span>No SKUs matches found</span>';
}  // end if

If that doesn’t get it, I would use the error_log() call to closely examine the output of wc_get_product_terms() to see if you are getting what you expect.