Wait, which tetromino was that?
JavaScript (ES10),  286  282 bytes
Expects (a)(b), where \$a\$ and \$b\$ are 2 lists of binary strings. Returns an integer between \$0\$ and \$6\$ for JLTIOZS, or \$-1\$ if there's no solution (but we're not supposed to support that).
a=&gt;b=&gt;&quot;0NF71ZMA13FM000F1F1F1IFL2R8I38LT357N368H&quot;.match(/../g).findIndex(p=&gt;b.some((r,y)=&gt;[...r].some((_,x)=&gt;!b.some((s,i)=&gt;[...a.map(B=r=&gt;'0b'+r),~0].flatMap(t=(r,Y,a)=&gt;~(q=((parseInt(p,36)||4369)&gt;&gt;(Y-y)*4&amp;15)&lt;&lt;x,t|=q&amp;a[Y+1],q|=q&amp;r?~0:r)+2**s.length?q:(i--,[]))[i]^B(s)|!t))))%14&gt;&gt;1

Try it online!
How?
Shape encoding
Each shape is encoded with 2 digits in base 36, which allows to store:
$$\lfloor 2\times\log_2 36\rfloor=10\text{ bits}$$
The bits are arranged in a \$4\times 4\$ matrix, with the piece wedged in the upper right corner. The least significant bit is mapped to the top-right cell and there are 6 implicit leading zeros.
Examples:

The 1st entry is 0N in base 36, which is \$23\$ in decimal and \$0000010111\$ in binary. This is a J.

The 6th entry is FM in base 36, which is \$562\$ in decimal and \$1000110010\$ in binary. This is a T.



All shapes can be encoded that way, except the vertical I. This one is encoded as 00 and its actual value (\$4369\$ in decimal) is hard-coded separately.
Main algorithm
The main algorithm consists of 5 nested loops where we try to put each shape \$p\$ at each possible position \$(x,y)\$ in the grid \$a\$ and figure out which one leads to the grid \$b\$.
Whenever a row is completed, we yield an empty array so that .flatMap() deletes this row and we decrement the index \$i\$ of the entry that needs to be read in the resulting array to account for the row shift.
We may end up with a negative \$i\$. But because we use a XOR for the comparison, undefined rows behave like they were set to \$0\$, which is what we want.
&quot;...&quot;.match(/../g)              // list of shapes
.findIndex(p =&gt;                 // for each shape p:
  b.some((r, y) =&gt;              //   for each y:
    [...r].some((_, x) =&gt;       //     for each x:
      !b.some((s, i)=&gt;          //       for each row s at position i in b:
        [ ...a.map(             //         using the helper function B, decode a[] by
            B = r =&gt; '0b' + r   //         converting each binary string to an integer
          ), ~0                 //         and append a full line at the bottom
        ].flatMap(t =           //         initialize t to a non-numeric value
        (r, Y, a) =&gt;            //         for each row r at position Y in this array:
          ~(                    //
            q = (               //           q is the 4-bit mask of the shape
              ( parseInt(p, 36) //           decoded from the base-36 value p,
                || 4369 )       //
              &gt;&gt; (Y - y) * 4    //           keeping only the bits for this row
              &amp; 15              //
            ) &lt;&lt; x,             //           and left-shifting by x
            t |= q &amp; a[Y + 1],  //           update the 'touching' mask
            q |= q &amp; r ? ~0     //           invalidate the row if q overlaps r
                       : r      //           otherwise, merge q and r
          ) + 2 ** s.length ?   //           if the resulting line is not full:
            q                   //             yield q
          :                     //           else:
            (i--, [])           //             decrement i and yield an empty array,
                                //             which results in the deletion of this
                                //             line by flatMap()
        )[i]                    //         end of flatMap(); extract the i-th row
        ^ B(s)                  //         the test fails if this row is not equal to s
        | !t                    //         or the shape is floating in the air
      )                         //       end of some()
    )                           //     end of some()
  )                             //   end of some()
)                               // end of findIndex()

Final result
The shapes are stored in the following order:
0N F7 1Z MA 13 FM 00 0F 1F 1F 1I FL 2R 8I 38 LT 35 7N 36 8H
0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19
J  J  L  L  T  T  I  I  O  O  Z  Z  S  S  J  J  L  L  T  T
which is why the final result is the value returned by .findIndex() modulo \$14\$, divided by \$2\$ and rounded towards \$0\$.
(NB: The shape O is stored twice so that it doesn't break the pattern.)