Efficiently remove duplicate elements from the list
I think you used a good way to filter out the duplicates, but I don't see why you feel the need to call .ToList() after that. A HashSet is perfectly iterable.
As such, I believe I would write your lengthy code somewhat differently as:
public async Task&lt;IReadonlyList&lt;T&gt;&gt; Execute&lt;T&gt;(IEnumerable&lt;int&gt; ids, Policy policy, Func&lt;CancellationToken, int, Task&lt;T&gt;&gt; mapperFunc) where T : class 
{
    return (await Task.WhenAll(
            new HashSet&lt;int&gt;(ids).Select( id =&gt; ProcessData( policy, ct =&gt; mapperFunc( ct, id ) ) ) ) )
        .Where( response =&gt; response != null )
        .ToList();
}

It will still remove all the duplicates, await all entries using the Task.WhenAll and remove the null values.
As for knowing if it is more efficient I can't tell without testing. I think it is more readable, though to be fair, I would probably rather assign the results to a variable before filtering them out, saving you some brackets.
public async Task&lt;IReadonlyList&lt;T&gt;&gt; Execute&lt;T&gt;(IEnumerable&lt;int&gt; ids, Policy policy, Func&lt;CancellationToken, int, Task&lt;T&gt;&gt; mapperFunc) where T : class 
{
    var responses = await Task.WhenAll(
            new HashSet&lt;int&gt;(ids).Select( id =&gt; ProcessData( policy, ct =&gt; mapperFunc( ct, id ) ) ) );

    return responses
        .Where( response =&gt; response != null )
        .ToList();
}