filter posts by meta key with pagination

You are doing a few different things wrong– or at least convoluted and suspect– in that code and I am sure that that is resulting in your query results getting out of sync with the pagination. You’ve got a couple of queries in there, including one made by query_posts which you should really never be using at all, plus some filters. Honestly, I didn’t crawl through it to work out exactly what is wrong but I believe that, primarily what you need is a meta query.

$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args = array(
    'post_type' => 'deals',
    'meta_query' => array(
        array(
            'key' => 'codes-deal',
            'compare' => 'EXISTS'
        )
    ),
    'paged' => $paged 
);
$query = new WP_Query( $args );

Secondarily, you need to clean up your pagination. See the first line. I can’t tell if you actually want to filter out posts that “that have certain meta_key” as you stated or if you want to filter the ones with 'codes-deals' = true but I went with what you said. You can edit in your other parameters– orderby, etc. Be aware that 'compare' => 'EXISTS' only works in 3.5 or better.

That code is almost a copy/paste from the Codex. All I did was edit in some of your values. The Codex is your friend. Love it.

Now, to apply that to the main query. For that you need pre_get_posts, which is a lot more convenient than trying to manipulate the WHERE clause with the post_where filter.

function exclude_codes_deals_wpse_92268($qry) {
    if (is_main_query()) {
        $qry->set('meta_query', array(array(
             'key' => 'codes-deal',
             'compare' => 'EXISTS'
        )));
        $qry->set('post_type', 'deals');
    }
}
add_filter('pre_get_posts','exclude_codes_deals_wpse_92268');

Untested but I believe I have that right. Again, you can edit in any other parameters you need.

That will globally alter your main query, which is what you said you wanted to do, but I have my doubts. With that code in place only the ‘deals’ post type will show up, unless you specifically create queries to pull other content. I suspect that there are other conditions for altering the query besides just that it is the main query.