Wordpress - WP_Query: Exclude hidden products from WooCommerce product list

As of Woocommerce 3. Visibility is changed to taxonomy instead of meta. So you need to change the meta_query to tax_query. To show only visible products,

'tax_query' => array(
    array(
        'taxonomy' => 'product_visibility',
        'field'    => 'name',
        'terms'    => 'exclude-from-catalog',
        'operator' => 'NOT IN',
    ),
),

and examples for Featured Products

'tax_query' => array(
    array(
        'taxonomy' => 'product_visibility',
        'field'    => 'name',
        'terms'    => 'featured',
    ),
),

Possible terms: 'exclude-from-search', 'exclude-from-catalog', 'featured', 'outofstock'.


Important: The following only works for WooCommerce versions less than 3.0. For a more up-to-date answer please see the other answer by kalle.

WooCommerce save this data as metadata so you'll need to run a Meta Query against the name _visibility. Something like:

'meta_query' => array(
    array(
        'key'       => '_visibility',
        'value'     => 'hidden',
        'compare'   => '!=',
    )
)

This will pull all posts that do not have meta _visibility equal to hidden.