Вполне себе оптимальное. Перебирается ровно столько сколько нужно.
Разве что вынести значение в переменную, чтоб лишний раз toLowerCase не делать:  
function solution(a) {
    return a.filter(item => filterBy.some(prop => {
       const value = item[prop].toLowerCase();
       return filterVal.some(i => value.includes(i));
    }));
}
console.log(solution(arr));